<template>
  <div ref="chartContainer" class="rose-chart-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as d3 from "d3";

interface RoseData {
  label: string;
  value: number;
  color: string;
}

interface RoseArcDatum extends d3.DefaultArcObject {
  data: RoseData;
  padAngle?: number;
  innerRadius: number;
  outerRadius: number;
}

const chartContainer = ref<HTMLElement>();
const chartData: RoseData[] = [
  { label: "产品A", value: 35, color: "#59a14f" },
  { label: "产品B", value: 25, color: "#f28e2b" },
  { label: "产品C", value: 20, color: "#e15759" },
  { label: "产品D", value: 15, color: "#76b7b2" },
  { label: "产品E", value: 5, color: "#4e79a7" },
];

let resizeObserver: ResizeObserver;

onMounted(() => {
  initChart();
  initResizeObserver();
});

onBeforeUnmount(() => {
  resizeObserver?.disconnect();
});

const initResizeObserver = () => {
  if (!chartContainer.value) return;
  resizeObserver = new ResizeObserver(() => initChart());
  resizeObserver.observe(chartContainer.value);
};

const initChart = () => {
  if (!chartContainer.value) return;

  // 清除旧图表
  d3.select(chartContainer.value).selectAll("*").remove();

  // 设置尺寸
  const width = chartContainer.value.clientWidth;
  const height = Math.min(width, 230);
  const radius = Math.min(width, height) / 2 * 0.8; // 使用80%的可用半径
  const innerRadius = radius * 0.2; // 内部圆环半径

  // 创建SVG容器
  const svg = d3
    .select(chartContainer.value)
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", `translate(${width / 2},${height / 2})`);

  // 创建工具提示
  const tooltip = createTooltip();

  // 创建角度比例尺（固定每个类别的角度范围）
  const angleScale = d3.scaleBand()
    .domain(chartData.map(d => d.label))
    .range([0, 2 * Math.PI])
    .padding(0); // 花瓣间的间距

  // 创建半径比例尺（使用平方根比例尺使面积与数值线性相关）
  const radiusScale = d3.scaleSqrt()
    .domain([0, d3.max(chartData, d => d.value) || 1])
    .range([0, radius]);

  // 创建弧生成器（南丁格尔玫瑰图不需要内半径）
const arc = d3.arc<RoseArcDatum>()
  .innerRadius(0)
  .outerRadius(d => radiusScale(d.data.value))
  .startAngle(d => angleScale(d.data.label) as number)
  .endAngle(d => (angleScale(d.data.label) as number) + angleScale.bandwidth());
  // .padAngle(0.01); // 现在类型正确

  // 创建饼图布局（仅用于数据结构转换）
  const pie = d3.pie<RoseData>()
    .value(d => d.value)
    .sort(null);

  // 绘制玫瑰图花瓣
  const arcs = svg
    .selectAll(".arc")
    .data(pie(chartData))
    .enter()
    .append("g")
    .attr("class", "arc");

  // 添加花瓣路径
  addArcPaths(arcs, arc);

  // 添加悬停效果
  addHoverEffects(arcs, tooltip);

  // 添加标签（南丁格尔玫瑰图通常不需要引导线）
  addLabels(arcs, arc, radiusScale, angleScale);
 // 添加中心圆环
  addInnerRing(svg, innerRadius);
  // 添加标题
  addTitle(svg, width);
};
// 添加中心圆环
const addInnerRing = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  innerRadius: number
) => {
  svg.append("circle")
    .attr("r", innerRadius)
    .attr("fill", "#06164a")
    .attr("stroke", "#ddd")
    .attr("stroke-width", 1);
};
const createTooltip = () : d3.Selection<HTMLDivElement, unknown, null, undefined>=> {
  if (!chartContainer.value) return d3.select(document.createElement('div'));
  return d3
    .select(chartContainer.value)
    .append("div")
    .attr("class", "rose-tooltip")
    .style("opacity", 0)
    .style("position", "absolute")
    .style("background", "rgba(0,0,0,0.8)")
    .style("color", "white")
    .style("padding", "8px 12px")
    .style("border-radius", "4px")
    .style("pointer-events", "none")
    .style("font-size", "14px");
};

const addArcPaths = (
  arcs: d3.Selection<SVGGElement, d3.PieArcDatum<RoseData>, SVGGElement, unknown>,
  arc: d3.Arc<any, RoseArcDatum>
) => {
  arcs
    .append("path")
    .attr("fill", (d) => d.data.color)
    .attr("stroke", "#fff")
    .attr("stroke-width", 1)
    .transition()
    .duration(1000)
    .attrTween("d", function (d:any) {
      const start: RoseArcDatum = {
        startAngle: 0,
        endAngle: 0,
        padAngle: 0,
        innerRadius: 0,  // 添加默认值
        outerRadius: 0,  // 添加默认值
        data: d.data,
      };
      const target: RoseArcDatum = { ...d,
         innerRadius: 0,  // 南丁格尔玫瑰图不需要内半径
        outerRadius: arc.outerRadius()(d), // 从弧生成器获取外半径
       };
      const interpolate = d3.interpolate(start, target);
      return (t) => arc(interpolate(t))!;
    });
};

const addHoverEffects = (
  arcs: d3.Selection<SVGGElement, d3.PieArcDatum<RoseData>, SVGGElement, unknown>,
  tooltip: d3.Selection<HTMLDivElement, unknown, null, undefined>
) => {
  arcs
    .select("path")
    .on("mouseover", function (event, d) {
      d3.select(this)
        .raise()
        .transition()
        .duration(200)
        .attr("stroke-width", 2)
        .attr("opacity", 0.9);

      // 工具提示位置计算
      const tooltipNode = tooltip.node();
      if (!tooltipNode) return;
      
      const tooltipWidth = tooltipNode.offsetWidth;
      const tooltipHeight = tooltipNode.offsetHeight;
      
      let left = event.clientX + 15;
      let top = event.clientY - tooltipHeight - 10;
      
      if (left + tooltipWidth > window.innerWidth) {
        left = event.clientX - tooltipWidth - 15;
      }
      
      if (top < 0) {
        top = event.clientY + 15;
      }

      tooltip
        .html(`<strong>${d.data.label}</strong><br>${d.data.value}%`)
        .style("left", `${left}px`)
        .style("top", `${top}px`)
        .transition()
        .duration(200)
        .style("opacity", 1);
    })
    .on("mouseout", function () {
      d3.select(this)
        .transition()
        .duration(300)
        .attr("stroke-width", 1)
        .attr("opacity", 1);

      tooltip.transition().duration(300).style("opacity", 0);
    });
};

const addLabels = (
  arcs: d3.Selection<SVGGElement, d3.PieArcDatum<RoseData>, SVGGElement, unknown>,
  _arc: d3.Arc<any, RoseArcDatum>,
  radiusScale: d3.ScalePower<number, number, never>,
  angleScale: d3.ScaleBand<string>
) => {
  arcs.each(function(d:any) {
    const g = d3.select(this);
    // const centroid = arc.centroid(d);
    const midAngle = (angleScale(d.data.label) as number + angleScale.bandwidth() / 2);
    
    // 计算标签位置（放在花瓣中间偏外）
    const labelRadius = radiusScale(d.data.value) * 0.7;
    const x = Math.cos(midAngle) * labelRadius;
    const y = Math.sin(midAngle) * labelRadius;
    
    // 根据位置决定文本对齐方式
    const textAnchor = Math.cos(midAngle) > 0 ? "start" : "end";
    const dx = Math.cos(midAngle) > 0 ? 5 : -5;
    
    // 添加文本
    g.append("text")
      .attr("transform", `translate(${x},${y})`)
      .attr("text-anchor", textAnchor)
      .attr("dy", "0.35em")
      .attr("dx", dx)
      .style("font-size", "12px")
      .style("font-weight", "bold")
      .style("fill", "#333")
      .text(d.data.label);
  });
};

const addTitle = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  width: number
) => {
  svg.append("text")
    .attr("text-anchor", "middle")
    .attr("dy", -width / 2 + 30)
    .style("font-size", "18px")
    .style("font-weight", "bold")
    .style("fill", "#333")
    .text("南丁格尔玫瑰图");
};
</script>

<style scoped>
.rose-chart-container {
  width: 100%;
  height: 100%;
}

.rose-tooltip {
  min-width: 100px;
  text-align: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
</style>